fix(postgresql,kingbase): quote foreign schema and table in REFERENCES - #2187
fix(postgresql,kingbase): quote foreign schema and table in REFERENCES#2187Aias00 wants to merge 1 commit into
Conversation
The foreign schema and table were concatenated raw while the foreign columns below were double-quoted. PostgreSQL/KingBase fold unquoted identifiers to lowercase, so mixed-case foreign table names produced a REFERENCES clause pointing at a non-existent relation. Wrap in double-quotes, matching the column quoting in the same method. Fixes OtterMind#2184 Co-Authored-By: Claude <noreply@anthropic.com>
Live-database verification (PostgreSQL 16)
The foreign columns were already double-quoted in the same method; this fix quotes the schema and table to match. |
|
Thanks for the live PostgreSQL verification. It confirms why the mixed-case referenced object cannot be resolved when it is left unquoted, but directly concatenating Please pass the raw schema, table, and column identifier components to Could you please rework this PR, as well as the other similar quote-related PRs, in that direction? If the current processor API cannot express an explicit always-quote/preserve-exact-name operation, please extend the shared SPI first instead of adding direct delimiters or plugin-local helpers. The shared contract also needs to escape embedded delimiter characters correctly and satisfy Please add automated tests rather than relying only on the manual PostgreSQL check. At minimum, cover:
It would be better to make this shared processor contract and its tests complete first, then rebase the individual dialect PRs onto it. |
|
Created the foundational SPI extension PR: #2234 It adds Once #2234 merges, I'll rework this PR and the other quoting PRs (#2145, #2169, #2185, #2186) to use |
|
Closing in favor of #2264 which uses the SPI quoteIdentifierAlways method per the maintainer review. |
…chema and table in REFERENCES Replaces direct " concatenation with the dialect-specific processor: PostgreSQLMetaData.POSTGRE_SQL_IDENTIFIER_PROCESSOR and KingBaseMetaData.KINGBASE_SQL_IDENTIFIER_PROCESSOR. Built on the SPI extension (OtterMind#2234). Closes OtterMind#2187 (superseded by this SPI-based approach) Co-Authored-By: Claude <noreply@anthropic.com>
Add a new SPI method that unconditionally quotes an identifier, preserving the exact name regardless of case or keyword status. Embedded delimiter characters are escaped per the dialect convention (double-quote "" for ", backtick `` for `, bracket ]] for ]). Fix removeIdentifierQuote to unescape doubled delimiters, satisfying the round-trip contract: removeIdentifierQuote(quoteIdentifierAlways(raw)).equals(raw). Implementations: - DefaultSQLIdentifierProcessor: double-quote + escape " -> "" - MysqlIdentifierProcessor: backtick + escape ` -> `` - SqlServerIdentifierProcessor: bracket + escape ] -> ]] Also add SNOWFLAKE_SQL_IDENTIFIER_PROCESSOR static field to SnowflakeMetaData, mirroring PostgreSQL/KingBase, to give Snowflake column-type enums access to the processor for downstream quoting PRs. Tests: 36 tests covering conditional vs always-quote, embedded delimiters, round-trip, reserved keywords, and case preservation across Default, MySQL, and SqlServer processors. Addresses the maintainer review on OtterMind#2187 requesting the shared SPI contract be extended before rebasing the individual dialect quoting PRs. Co-Authored-By: Claude <noreply@anthropic.com>
Replaces direct backtick concatenation with KingBaseMetaData.KINGBASE_SQL_IDENTIFIER_PROCESSOR.quoteIdentifierAlways, per the maintainer review on OtterMind#2187. Built on the SPI extension (OtterMind#2234). Closes OtterMind#2145 (superseded by this SPI-based approach) Co-Authored-By: Claude <noreply@anthropic.com>
…chema and table in REFERENCES Replaces direct " concatenation with the dialect-specific processor: PostgreSQLMetaData.POSTGRE_SQL_IDENTIFIER_PROCESSOR and KingBaseMetaData.KINGBASE_SQL_IDENTIFIER_PROCESSOR. Built on the SPI extension (OtterMind#2234). Closes OtterMind#2187 (superseded by this SPI-based approach) Co-Authored-By: Claude <noreply@anthropic.com>
Add a new SPI method that unconditionally quotes an identifier, preserving the exact name regardless of case or keyword status. Embedded delimiter characters are escaped per the dialect convention (double-quote "" for ", backtick `` for `, bracket ]] for ]). Fix removeIdentifierQuote to unescape doubled delimiters, satisfying the round-trip contract: removeIdentifierQuote(quoteIdentifierAlways(raw)).equals(raw). Implementations: - DefaultSQLIdentifierProcessor: double-quote + escape " -> "" - MysqlIdentifierProcessor: backtick + escape ` -> `` - SqlServerIdentifierProcessor: bracket + escape ] -> ]] Also add SNOWFLAKE_SQL_IDENTIFIER_PROCESSOR static field to SnowflakeMetaData, mirroring PostgreSQL/KingBase, to give Snowflake column-type enums access to the processor for downstream quoting PRs. Tests: 36 tests covering conditional vs always-quote, embedded delimiters, round-trip, reserved keywords, and case preservation across Default, MySQL, and SqlServer processors. Addresses the maintainer review on OtterMind#2187 requesting the shared SPI contract be extended before rebasing the individual dialect quoting PRs. Co-Authored-By: Claude <noreply@anthropic.com>
Add a new SPI method that unconditionally quotes an identifier, preserving the exact name regardless of case or keyword status. Embedded delimiter characters are escaped per the dialect convention (double-quote "" for ", backtick `` for `, bracket ]] for ]). Fix removeIdentifierQuote to unescape doubled delimiters, satisfying the round-trip contract: removeIdentifierQuote(quoteIdentifierAlways(raw)).equals(raw). Implementations: - DefaultSQLIdentifierProcessor: double-quote + escape " -> "" - MysqlIdentifierProcessor: backtick + escape ` -> `` - SqlServerIdentifierProcessor: bracket + escape ] -> ]] Also add SNOWFLAKE_SQL_IDENTIFIER_PROCESSOR static field to SnowflakeMetaData, mirroring PostgreSQL/KingBase, to give Snowflake column-type enums access to the processor for downstream quoting PRs. Tests: 36 tests covering conditional vs always-quote, embedded delimiters, round-trip, reserved keywords, and case preservation across Default, MySQL, and SqlServer processors. Addresses the maintainer review on OtterMind#2187 requesting the shared SPI contract be extended before rebasing the individual dialect quoting PRs. Co-Authored-By: Claude <noreply@anthropic.com>
* feat(spi): add quoteIdentifierAlways to ISQLIdentifierProcessor Add a new SPI method that unconditionally quotes an identifier, preserving the exact name regardless of case or keyword status. Embedded delimiter characters are escaped per the dialect convention (double-quote "" for ", backtick `` for `, bracket ]] for ]). Fix removeIdentifierQuote to unescape doubled delimiters, satisfying the round-trip contract: removeIdentifierQuote(quoteIdentifierAlways(raw)).equals(raw). Implementations: - DefaultSQLIdentifierProcessor: double-quote + escape " -> "" - MysqlIdentifierProcessor: backtick + escape ` -> `` - SqlServerIdentifierProcessor: bracket + escape ] -> ]] Also add SNOWFLAKE_SQL_IDENTIFIER_PROCESSOR static field to SnowflakeMetaData, mirroring PostgreSQL/KingBase, to give Snowflake column-type enums access to the processor for downstream quoting PRs. Tests: 36 tests covering conditional vs always-quote, embedded delimiters, round-trip, reserved keywords, and case preservation across Default, MySQL, and SqlServer processors. Addresses the maintainer review on #2187 requesting the shared SPI contract be extended before rebasing the individual dialect quoting PRs. Co-Authored-By: Claude <noreply@anthropic.com> * fix(spi): enforce identifier quoting contract --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: zgq <openai0229@gmail.com>
Related issue
Closes #2184
Summary
PostgreSQLIndexTypeEnum.buildForeignColum (and the identical KingBaseIndexTypeEnum) concatenated getForeignSchemaName() and getForeignTableName() raw into the REFERENCES clause, while the foreign columns below were double-quoted. PostgreSQL/KingBase fold unquoted identifiers to lowercase, so a foreign table with an uppercase/mixed-case name produced a REFERENCES clause pointing at a non-existent relation. Wrapped both in double-quotes, matching the column quoting in the same method. Applied to both PostgreSQL and KingBase.
Verification
Contributor declaration
AI assistance: The fix, verification, and PR description were produced with Claude Code assistance.